package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qinglei.recoup.system.dao.BedHealthStateMapper;
import com.qinglei.recoup.system.dao.DeviceRealTimeDataMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.domain.vo.RadarBedVo;
import com.qinglei.recoup.system.enums.BedStatusEnum;
import com.qinglei.recoup.system.pojo.BedInformationVO;
import com.qinglei.recoup.system.pojo.BedMonitorTimeVO;
import com.qinglei.recoup.system.pojo.BedStatusVO;
import com.qinglei.recoup.system.pojo.event.VitalSignsAlarmDto;
import com.qinglei.recoup.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceRealTimeDataServiceImpl implements DeviceRealTimeDataService {
    @Autowired
    private DeviceRealTimeDataMapper deviceRealTimeDataMapper;
    @Resource
    private RadarBedService radarBedService;
    @Resource
    private EventProcService eventProcService;
    @Autowired
    private BedService bedService;
    @Resource
    private BedHealthStateMapper bedHealthStateMapper;
    @Autowired
    private BedMonitorTimeService bedMonitorTimeService;

    @Override
    public List<BedStatusVO> getBedShowListByUser(String sn, Long userId, Integer roleId) {
        List<BedStatusVO> resList = new ArrayList<>();
        List<Integer> bedIdsByUser = deviceRealTimeDataMapper.getBedIdsBySn(sn);
        if (CollectionUtils.isEmpty(bedIdsByUser) || bedIdsByUser.get(0) == 0) {
            return resList;
        }
        if (bedIdsByUser.get(0) == -1) {
            bedIdsByUser = null;
        }
        Integer tenantId = 1;
        List<BedStatusBO> bedStatusBOS = deviceRealTimeDataMapper.selectBedStatusListByIds(bedIdsByUser, tenantId);
        List<Integer> bedIds = bedStatusBOS.stream().map(BedStatusBO::getBedId).collect(Collectors.toList());
        Map<Integer, RadarBedVo> radarBedMapByBedIds = radarBedService.getRadarBedMapByBedIds(bedIds);
        bedStatusBOS.forEach(bedStatusBO -> {
            BedStatusVO bedStatusVO = new BedStatusVO();
            BeanUtils.copyProperties(bedStatusBO, bedStatusVO);
            setByStatus(bedStatusBO, bedStatusVO);
            if (bedStatusBO.getHealthyBpm() != null && bedStatusVO.getStatus() == BedStatusEnum.NORMAL.getCode()) {
                switch (bedStatusBO.getHealthyBpm()) {
                    case BedHealthState.SUB_STATUS_BREATH_NORMAL:
                        bedStatusVO.setHealthyStatusName("呼吸正常");
                        break;
                    case BedHealthState.SUB_STATUS_BREATH_HIGHT:
                        bedStatusVO.setHealthyStatusName("呼吸过速");
                        break;
                    case BedHealthState.SUB_STATUS_BREATH_LOW:
                        bedStatusVO.setHealthyStatusName("呼吸暂停过久");
                        break;
                    case BedHealthState.SUB_STATUS_HEART_NORMAL:
                        bedStatusVO.setHealthyStatusName("心跳正常");
                        break;
                    case BedHealthState.SUB_STATUS_HEART_HIGHT:
                        bedStatusVO.setHealthyStatusName("心跳过速");
                        break;
                    case BedHealthState.SUB_STATUS_HEART_LOW:
                        bedStatusVO.setHealthyStatusName("心跳过缓");
                        break;
                    default:
                }
                Long eventId = bedStatusBO.getEventId();
                Integer bedId = bedStatusBO.getBedId();
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("event_id", eventId);
                queryWrapper.eq("bed_id", bedId);
                EventProc eventProc = eventProcService.getOne(queryWrapper);
                if (eventProc != null && eventProc.getStatus() == 3) {
                    bedStatusVO.setHealthyBpm(BedHealthState.SUB_STATUS_PROCESSING);
                }

            } else {
                bedStatusVO.setHealthyBpm(null);
            }
            if (radarBedMapByBedIds.containsKey(bedStatusBO.getBedId())) {
                bedStatusVO.setSn(radarBedMapByBedIds.get(bedStatusBO.getBedId()).getSnCode());
            }
            // 设置遗漏任务数量
//            bedStatusVO.setMissedEventNum(eventProcService.getMissedEventNumByBed(bedStatusVO.getBedId()));
            resList.add(bedStatusVO);
        });

        return resList;
    }

    @Override
    public Bed getBedBySn(String sn) {
        return deviceRealTimeDataMapper.getBedBySn(sn);
    }

    @Override
    public BedInformationVO getBedInformationBySn(String sn) {
        return deviceRealTimeDataMapper.getBedInformationBySn(sn);
    }

    @Override
    public List<VitalSignsAlarmDto> getVitalSignsAlarmBySn(String sn, Date nowDate) {
        return deviceRealTimeDataMapper.getVitalSignsAlarmBySn(sn, nowDate);
    }

    private void setByStatus(BedStatusBO bedStatusBO, BedStatusVO bedStatusVO) {

        // 获取当前监测时段
        BedMonitorTimeVO bedCurMonitorTime = bedService.getBedCurMonitorTime(bedStatusBO.getBedId());

        if (Bed.RADAR_OFFLINE == bedStatusBO.getIsRadarOnline()) {
            // 设备离线
            bedStatusVO.setStatus(BedStatusEnum.DEVICE_OFFLINE.getCode());
            bedStatusVO.setStatusName(BedStatusEnum.DEVICE_OFFLINE.getName());
            bedStatusVO.setSubStatus(0);
            if (bedCurMonitorTime != null) {
                bedStatusVO.setCurMonitorTime(bedCurMonitorTime.getStartTime() + '-' + bedCurMonitorTime.getEndTime());
            }
        } else if (bedStatusBO.getRadarType() == Radar.TYPE_BED && bedStatusBO.getIsRadarOn() == Bed.RADAR_OFF) {
            // 监测仪关闭
            bedStatusVO.setStatus(BedStatusEnum.MONITOR_OFF.getCode());
            bedStatusVO.setStatusName(BedStatusEnum.MONITOR_OFF.getName());
            bedStatusVO.setDescription(bedStatusBO.getRemarks());
            bedStatusVO.setMissedEventNum(eventProcService.getMissedEventNumByBed(bedStatusBO.getBedId()));
        } else if (bedStatusBO.getRadarType() == Radar.TYPE_BED && bedCurMonitorTime == null) {
            // 不在监测时段
            bedStatusVO.setStatus(BedStatusEnum.NON_IN_MONITOR.getCode());
            bedStatusVO.setStatusName(BedStatusEnum.NON_IN_MONITOR.getName());
            bedStatusVO.setMissedEventNum(eventProcService.getMissedEventNumByBed(bedStatusBO.getBedId()));
            BedMonitorTimeVO nextMonitorTime = bedMonitorTimeService.getNextMonitorTime(bedStatusBO.getBedId());
            if (nextMonitorTime != null) {
                bedStatusVO.setCurMonitorTime(nextMonitorTime.getStartTime() + '-' + nextMonitorTime.getEndTime());
            }
        } else if (Bed.STATUS_ALARM == bedStatusBO.getStatus()) {

            if (bedStatusBO.getHappenTime() != null) {
                int duration = (int) (LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) -
                        bedStatusBO.getHappenTime().toEpochSecond(ZoneOffset.of("+8")));
                bedStatusVO.setDuration(duration);
            } else {
                bedStatusVO.setDuration(0);
            }
            // 在监测时段，设置监测时间
            if (bedStatusBO.getRadarType() == Radar.TYPE_BED) {
                bedStatusVO.setCurMonitorTime(bedCurMonitorTime.getStartTime() + '-' + bedCurMonitorTime.getEndTime());
            }
            System.err.println(bedStatusBO);
            // 是否报警
            if (EventProc.STATUS_HAPPEN == bedStatusBO.getEventStatus() || EventProc.STATUS_PROCESSING == bedStatusBO.getEventStatus()) {
                // 报警发生
                bedStatusVO.setStatus(BedStatusEnum.ALARM.getCode());
                if (bedStatusBO.getRadarType() == Radar.TYPE_BED) {
                    bedStatusVO.setSubStatus(BedStatusEnum.AlarmEnum.OUT_BED_TOO_LONG.getCode());
                    bedStatusVO.setStatusName(BedStatusEnum.AlarmEnum.OUT_BED_TOO_LONG.getName());
                } else {
                    bedStatusVO.setSubStatus(BedStatusEnum.AlarmEnum.FALL_DOWN.getCode());
                    bedStatusVO.setStatusName(BedStatusEnum.AlarmEnum.FALL_DOWN.getName());
                }
            } else if (EventProc.STATUS_FINISHED == bedStatusBO.getEventStatus()) {
                // 处理中
                bedStatusVO.setStatus(BedStatusEnum.PROCESSING.getCode());
                if (bedStatusBO.getRadarType() == Radar.TYPE_BED) {
                    bedStatusVO.setStatusName(BedStatusEnum.AlarmEnum.OUT_BED_TOO_LONG.getName());
                } else {
                    bedStatusVO.setStatusName(BedStatusEnum.AlarmEnum.FALL_DOWN.getName());
                }
            } else {
                log.warn("error alarm status:{}", bedStatusBO);
            }
        } else if (Bed.STATUS_NORMAL == bedStatusBO.getStatus()) {
            // 在监测时段，设置监测时间
            if (bedStatusBO.getRadarType() == Radar.TYPE_BED) {
                bedStatusVO.setCurMonitorTime(bedCurMonitorTime.getStartTime() + '-' + bedCurMonitorTime.getEndTime());
            }
            bedStatusVO.setStatus(BedStatusEnum.NORMAL.getCode());
            bedStatusVO.setMissedEventNum(eventProcService.getMissedEventNumByBed(bedStatusBO.getBedId()));
            if (Bed.SUB_STATUS_OUT_BED == bedStatusBO.getSubStatus()) {
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.OUT_BED.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.OUT_BED.getName());
                if (bedStatusBO.getHappenTime() == null) {
                    bedStatusBO.setHappenTime(LocalDateTime.now());
                    log.warn("HappenTime in null bedStatusBO:{}", bedStatusBO);
                }
                int duration = (int) (LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) -
                        bedStatusBO.getHappenTime().toEpochSecond(ZoneOffset.of("+8")));
                bedStatusVO.setDuration(Math.max(duration, 1));
            } else if (Bed.SUB_STATUS_CLEAR == bedStatusBO.getSubStatus()) {  //清醒
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.CLEAR.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.CLEAR.getName());
                this.setBedHealthState(bedStatusBO.getBedId(), bedStatusVO);

            } else if (Bed.SUB_STATUS_LIGHT_SLEEP == bedStatusBO.getSubStatus()) {
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.LIGHT_SLEEP.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.LIGHT_SLEEP.getName());
                this.setBedHealthState(bedStatusBO.getBedId(), bedStatusVO);
            } else if (Bed.SUB_STATUS_DEEP_SLEEP == bedStatusBO.getSubStatus()) {
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.DEEP_SLEEP.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.DEEP_SLEEP.getName());
                this.setBedHealthState(bedStatusBO.getBedId(), bedStatusVO);
            } else if (Bed.SUB_STATUS_EXIST_NONE == bedStatusBO.getSubStatus()) {
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.EXIST_NONE.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.EXIST_NONE.getName());
            } else if (Bed.SUB_STATUS_EXIST_SOMEONE == bedStatusBO.getSubStatus()) {
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.EXIST_SOMEONE.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.EXIST_SOMEONE.getName());
            } else {
                log.warn("error normal status:{}", bedStatusBO);
                bedStatusVO.setSubStatus(BedStatusEnum.NormalEnum.CLEAR.getCode());
                bedStatusVO.setStatusName(BedStatusEnum.NormalEnum.CLEAR.getName());
            }
        } else {
            log.warn("error status:{}", bedStatusBO);
        }
    }

    private void setBedHealthState(Integer bedId, BedStatusVO bedStatusVO) {
        BedHealthState bedHealthState = bedHealthStateMapper.selectOne(new QueryWrapper<BedHealthState>().lambda()
                .eq(BedHealthState::getBedId, bedId).last("LIMIT 1"));
        if (bedHealthState != null) {
            bedStatusVO.setHealthyBpm(bedHealthState.getType());
            if (bedHealthState.getType() == BedHealthState.SUB_STATUS_BREATH_HIGHT) {
                bedStatusVO.setHealthyStatusName("呼吸过速");
            }
            if (bedHealthState.getType() == BedHealthState.SUB_STATUS_BREATH_LOW) {
                bedStatusVO.setHealthyStatusName("呼吸暂停过久");
            }
            if (bedHealthState.getType() == BedHealthState.SUB_STATUS_HEART_HIGHT) {
                bedStatusVO.setHealthyStatusName("心跳过速");
            }
            if (bedHealthState.getType() == BedHealthState.SUB_STATUS_HEART_LOW) {
                bedStatusVO.setHealthyStatusName("心跳过缓");
            }

        }
    }


}
